import { beforeEach, describe, expect, mock, test } from "bun:test"; const ownerRecord = { publicSlug: "demo-user", nickname: "Demo", avatar: "https://cdn.example.com/avatar.png", avatarVisibility: "public", bioVisibility: "public", bioMarkdown: "hello bio", socialLinksJson: "[]", status: "active", }; const selectMock = mock(() => ({ from: () => ({ where: () => ({ limit: async () => [ownerRecord], }), }), })); const getPublicHubBySlug = mock(async () => ({ modules: { posts: { items: [ { slug: "hub-p1", title: "hub-post-1" }, { slug: "hub-p2", title: "hub-post-2" }, ], total: 6, }, timeline: { items: [ { id: 101, title: "hub-t1" }, { id: 102, title: "hub-t2" }, ], total: 8, }, reading: { items: [ { id: 2, title: "r1" }, { id: 3, title: "r2" }, ], total: 6, }, }, posts: { items: [ { slug: "legacy-p1", title: "legacy-post-1" }, { slug: "legacy-p2", title: "legacy-post-2" }, { slug: "legacy-p3", title: "legacy-post-3" }, { slug: "legacy-p4", title: "legacy-post-4" }, ], total: 9, }, timeline: { items: [ { id: 201, title: "legacy-t1" }, { id: 202, title: "legacy-t2" }, { id: 203, title: "legacy-t3" }, ], total: 11, }, rssItems: { items: [ { id: 2, title: "r1" }, { id: 3, title: "r2" }, { id: 4, title: "r3" }, { id: 5, title: "r4" }, { id: 6, title: "r5" }, ], total: 6, }, })); const parseSocialLinksJson = mock(() => [ { label: "x", href: "https://x.com/demo", visibility: "public" }, { label: "mail", href: "mailto:demo@example.com", visibility: "private" }, ]); mock.module("drizzle-pkg/lib/db", () => ({ dbGlobal: { select: selectMock, }, })); mock.module("drizzle-pkg/lib/schema/auth", () => ({ users: { publicSlug: "publicSlug", status: "status", }, })); mock.module("drizzle-orm", () => ({ and: (...conditions: unknown[]) => conditions, eq: (a: unknown, b: unknown) => [a, b], })); mock.module("#server/service/profile", () => ({ parseSocialLinksJson, })); mock.module("#server/service/public-hub", () => ({ getPublicHubBySlug, })); globalThis.defineEventHandler ??= ((handler: unknown) => handler) as never; globalThis.createError ??= ((input: { statusCode: number; statusMessage: string }) => { const error = new Error(input.statusMessage) as Error & { statusCode: number; statusMessage: string; }; error.statusCode = input.statusCode; error.statusMessage = input.statusMessage; return error; }) as never; globalThis.R ??= { success: (data: unknown) => data, }; const handler = (await import("./[publicSlug].get")).default; describe("GET /api/public/profile/:publicSlug", () => { beforeEach(() => { ownerRecord.publicSlug = "demo-user"; ownerRecord.nickname = "Demo"; ownerRecord.avatar = "https://cdn.example.com/avatar.png"; ownerRecord.avatarVisibility = "public"; ownerRecord.bioVisibility = "public"; ownerRecord.bioMarkdown = "hello bio"; ownerRecord.socialLinksJson = "[]"; ownerRecord.status = "active"; selectMock.mockClear(); getPublicHubBySlug.mockClear(); parseSocialLinksJson.mockClear(); }); test("通过 public-hub 一次调用返回 modules 与 legacy 字段", async () => { const result = await handler({ context: { params: { publicSlug: "demo-user", }, }, } as never); expect(getPublicHubBySlug).toHaveBeenCalledWith("demo-user"); expect(getPublicHubBySlug).toHaveBeenCalledTimes(1); expect(parseSocialLinksJson).toHaveBeenCalledTimes(1); expect(selectMock).toHaveBeenCalledTimes(1); expect(result).toEqual({ user: { publicSlug: "demo-user", nickname: "Demo", avatar: "https://cdn.example.com/avatar.png", }, bio: { markdown: "hello bio", }, links: [{ label: "x", href: "https://x.com/demo", visibility: "public" }], modules: { posts: { items: [ { slug: "hub-p1", title: "hub-post-1" }, { slug: "hub-p2", title: "hub-post-2" }, ], total: 6, }, timeline: { items: [ { id: 101, title: "hub-t1" }, { id: 102, title: "hub-t2" }, ], total: 8, }, reading: { items: [ { id: 2, title: "r1" }, { id: 3, title: "r2" }, ], total: 6, }, }, posts: { items: [ { slug: "legacy-p1", title: "legacy-post-1" }, { slug: "legacy-p2", title: "legacy-post-2" }, { slug: "legacy-p3", title: "legacy-post-3" }, { slug: "legacy-p4", title: "legacy-post-4" }, ], total: 9, }, timeline: { items: [ { id: 201, title: "legacy-t1" }, { id: 202, title: "legacy-t2" }, { id: 203, title: "legacy-t3" }, ], total: 11, }, rssItems: { items: [ { id: 2, title: "r1" }, { id: 3, title: "r2" }, { id: 4, title: "r3" }, { id: 5, title: "r4" }, { id: 6, title: "r5" }, ], total: 6, }, }); }); test("publicSlug 缺失时返回 400,且不触发下游 service", async () => { await expect( handler({ context: { params: {}, }, } as never), ).rejects.toMatchObject({ statusCode: 400, statusMessage: "无效主页", }); expect(selectMock).toHaveBeenCalledTimes(0); expect(parseSocialLinksJson).toHaveBeenCalledTimes(0); expect(getPublicHubBySlug).toHaveBeenCalledTimes(0); }); test("publicSlug 非法时返回 400,且不触发下游 service", async () => { await expect( handler({ context: { params: { publicSlug: 123, }, }, } as never), ).rejects.toMatchObject({ statusCode: 400, statusMessage: "无效主页", }); expect(selectMock).toHaveBeenCalledTimes(0); expect(parseSocialLinksJson).toHaveBeenCalledTimes(0); expect(getPublicHubBySlug).toHaveBeenCalledTimes(0); }); test("owner 不存在或非 active 时返回 404", async () => { selectMock.mockImplementationOnce(() => ({ from: () => ({ where: () => ({ limit: async () => [], }), }), })); await expect( handler({ context: { params: { publicSlug: "demo-user", }, }, } as never), ).rejects.toMatchObject({ statusCode: 404, statusMessage: "未找到", }); expect(selectMock).toHaveBeenCalledTimes(1); expect(parseSocialLinksJson).toHaveBeenCalledTimes(0); expect(getPublicHubBySlug).toHaveBeenCalledTimes(0); }); test("avatarVisibility 非 public 时 avatar 为 null", async () => { ownerRecord.avatarVisibility = "private"; const result = await handler({ context: { params: { publicSlug: "demo-user", }, }, } as never); expect(result.user.avatar).toBeNull(); expect(selectMock).toHaveBeenCalledTimes(1); expect(parseSocialLinksJson).toHaveBeenCalledTimes(1); expect(getPublicHubBySlug).toHaveBeenCalledTimes(1); }); test("bioVisibility 非 public 时 bio 为 null", async () => { ownerRecord.bioVisibility = "private"; const result = await handler({ context: { params: { publicSlug: "demo-user", }, }, } as never); expect(result.bio).toBeNull(); expect(selectMock).toHaveBeenCalledTimes(1); expect(parseSocialLinksJson).toHaveBeenCalledTimes(1); expect(getPublicHubBySlug).toHaveBeenCalledTimes(1); }); test("无 bioMarkdown 时 bio 为 null", async () => { ownerRecord.bioMarkdown = ""; const result = await handler({ context: { params: { publicSlug: "demo-user", }, }, } as never); expect(result.bio).toBeNull(); expect(selectMock).toHaveBeenCalledTimes(1); expect(parseSocialLinksJson).toHaveBeenCalledTimes(1); expect(getPublicHubBySlug).toHaveBeenCalledTimes(1); }); });